package com.cgwx.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.cgwx.auth.util.TreeUtil.TreeUtils;
import com.cgwx.config.BusinessException;
import com.cgwx.data.dto.NpjFileFolder;
import com.cgwx.entity.*;
import com.cgwx.mapper.*;
import com.cgwx.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;

@Service
@Slf4j
public class FolderServiceImpl implements IFolderService {

    @Resource
    private FolderMapper folderMapper;

    @Resource
    private FileMapper fileMapper;

    @Resource
    private FavoritesMapper favoritesMapper;

    @Resource
    private PersonalRecycleBinMapper personalRecycleBinMapper;

    @Resource
    private SharedMapper sharedMapper;

    @Resource
    private IFileService fileService;

    @Resource
    private IFolderService folderService;

    @Resource
    private IRoomService roomService;

    @Resource
    private IAuthorityService authorityService;

    @Resource
    private IUtilService utilService;

    @Value("${nonPj}")
    private String nonPj;

    @Override
    public List<Folder> getPersonalTree(String account) {
        String roomId = roomService.getPersonalRoom(account);
        List<Folder> folders = folderMapper.getAllFolderByRoomId(roomId);
        //获取从x开始的子树
        folders = TreeUtils.build(folders, "root");
        return folders;
    }

    @Override
    public List<Folder> getFolderTree(String account, String deptId, String roomId, String type, String visibility) {
        List<Folder> folders = folderMapper.getAllFolderByRoomId(roomId);
        Comparator<Folder> comparator = (o1, o2) -> {
            if(o1.getTag() != null && o2.getTag() == null) return -1;
            else if(o1.getTag() == null && o2.getTag() != null) return 1;
            return o2.getCreateTime().compareTo(o1.getCreateTime());
        };
        List<Folder> folders0 = new ArrayList<>();
        if(type.equals("dept") || type.equals("company")){
            FileFolder fileFolder = new FileFolder();
            fileFolder.setEntityRoom(roomId);
            fileFolder.setOwnerAccount(account);
            fileFolder.setFileId(deptId);
            //当前空间这个人有权限的
            List<FileFolder> fileFolders = fileMapper.getAuthorityFileFolder0(fileFolder);
            if(visibility != null && visibility.equals("true")){
                for(Folder folder: folders){
                    if(!authorityService.checkAuthority(account, deptId, folder.getEntityId()).equals("0")) folders0.add(folder);
                }
            }
            else{
                Set<String> parentIds = new HashSet<>();
                for(FileFolder fileFolder1 : fileFolders) parentIds.add(fileFolder1.getParentId());
                for(Folder folder: folders){
                    if(!authorityService.checkAuthority(account, deptId, folder.getEntityId()).equals("0") && (parentIds.contains(folder.getEntityId()) || folder.getTag() == null)) folders0.add(folder);
                }
            }
            folders0.sort(comparator);
            folders = TreeUtils.build(folders0, "root");
        }
        else{
            folders.sort(comparator);
            folders = TreeUtils.build(folders, "root");
        }
        if(folders.size() > 1){
            log.warn("getFolderTree: 构造文件树出错!");
            throw new BusinessException("构造文件树出错!");
        }
        return folders;
    }

    @Override
    public List<NpjFileFolder> globalFileSearch(String account, String depId, String keyword, String visibility, String type, String column, String sort) {
        List<FileFolder> fileFolders;
        List<NpjFileFolder> npjFileFolders = new ArrayList<>();
        FileFolder fileFolder0;
        if(keyword == null || keyword.isEmpty()) return npjFileFolders;
        Room room = roomService.getRoom(account, depId, type);
        fileFolder0 = new FileFolder();
        fileFolder0.setEntityName(keyword);
        fileFolder0.setOwnerAccount(account);
        fileFolder0.setFileUrl(depId);
        fileFolder0.setEntityRoom(room.getId());
        fileFolder0.setColumn(column);
        fileFolder0.setSort(sort);
        //打开权限文件夹
        if(!room.getRoomType().equals("staff")) fileFolders = fileMapper.getAuthorityFileFolderGlobal(fileFolder0);
        else fileFolders = fileMapper.getFileFolderGlobal(fileFolder0);
        List<FileFolder> fileFolders2 = new ArrayList<>();
        for(FileFolder fileFolder: fileFolders){
            if(fileFolder.getAuthorityLevel() == null) fileFolder.setAuthorityLevel("4");
            else if(account.equals(fileFolder.getOwnerAccount())) fileFolder.setAuthorityLevel("4");
            if(visibility != null && visibility.equals("true")){
                fileFolders2.add(fileFolder);
            }
            else{
                FileFolder fileFolderSearch = new FileFolder();
                fileFolderSearch.setParentId(fileFolder.getEntityId());
                fileFolderSearch.setOwnerAccount(account);
                fileFolderSearch.setEntityRoom(depId);
                if(!fileMapper.getAuthorityFileFolder(fileFolderSearch).isEmpty() || fileFolder.getTag() == null || fileFolder.getTag().isEmpty()) {
                    fileFolders2.add(fileFolder);
                }
            }
        }
        Map<String, String> map = new HashMap<>();
        map.put("fileNum", keyword);
        map.put("type", type);
        String entityIdStr = utilService.getMethod(nonPj + "/nonPj/getByFileNum", map);
        List<String> entityIds = JSONObject.parseArray(entityIdStr, String.class);
        List<String> entityIds2 = new ArrayList<>();
        for(FileFolder fileFolder: fileFolders2) entityIds2.add(fileFolder.getEntityId());
        for (String entityId : entityIds) {
            if(!entityIds2.contains(entityId)){
                FileFolder fileFolder = new FileFolder();
                fileFolder.setEntityId(entityId);
                fileFolders2.addAll(fileMapper.getFileFolderBase(fileFolder));
            }
        }
        //联查编审批文件
        for(FileFolder fileFolder: fileFolders2) {
            NpjFileFolder npjFileFolder = new NpjFileFolder(fileFolder);
            String parentId = npjFileFolder.getParentId();
            StringBuilder parentPathname = new StringBuilder();
            boolean flag = false;//父文件夹被删了(脏数据)
            while (parentId != null && !parentId.equals("root")) {
                Folder folder = new Folder();
                folder.setEntityId(parentId);
                List<Folder> folders = folderMapper.getFolder(folder);
                if(folders.isEmpty()){
                    flag = true;
                    break;
                }
                folder = folders.get(0);
                parentPathname.insert(0, folder.getEntityName() + "/");
                parentId = folder.getParentId();
            }
            if (flag) continue;
            String path = parentPathname.toString();
            if (!path.isEmpty()) npjFileFolder.setLocation(parentPathname.substring(0, parentPathname.length() - 1));
            if(fileFolder.getTag() != null && fileFolder.getTag().equals("签批文件")){
                //通过entityId查询文件编号
                map = new HashMap<>();
                map.put("entityId", fileFolder.getEntityId());
                String fileNum = utilService.getMethod(nonPj + "/nonPj/getFileNumByEntityId", map);
                if(fileNum == null || fileNum.isEmpty() || fileNum.equals("[]")) continue;
                npjFileFolder.setFileNum(fileNum);
                npjFileFolders.add(npjFileFolder);
            }
            else npjFileFolders.add(npjFileFolder);
        }
        //排序
        if(column != null && !column.isEmpty()) npjFileFolders = utilService.sortGlobal(npjFileFolders, column, sort);
        return npjFileFolders;
    }

    @Override
    public List<FileFolder> OpenFolder(String account, String depId, String entityId, String keyword, String type, String column, String sort, String visibility) {
        List<FileFolder> fileFolders;
        FileFolder fileFolder0;
        List<String> fileFavorites;
        List<String> folderFavorites;
        switch (type) {
            case "staff":
            case "me":
            case "Me":
            case "SharedMe":
            case "MyShared":
                fileFolder0 = new FileFolder();
                fileFolder0.setParentId(entityId);
                fileFolder0.setEntityName(keyword);
                fileFolder0.setColumn(column);
                fileFolder0.setSort(sort);
                fileFolders = fileMapper.getFileFolder(fileFolder0);
                fileFavorites = fileService.OpenPersonalFavorites(entityId, account);
                folderFavorites = OpenPersonalFavorites(entityId, account);
                for (FileFolder fileFolder : fileFolders) {
                    if (folderFavorites.contains(fileFolder.getEntityId())) fileFolder.setIsFavorite("true");
                    else if (fileFavorites.contains(fileFolder.getEntityId())) fileFolder.setIsFavorite("true");
                    else fileFolder.setIsFavorite("false");
                }
                break;
            case "Favorites":
            case "company":
            case "dept":
                // 鉴权
                fileFolder0 = new FileFolder();
                fileFolder0.setParentId(entityId);
                fileFolder0.setEntityName(keyword);
                fileFolder0.setOwnerAccount(account);
                fileFolder0.setEntityRoom(depId);
                fileFolder0.setColumn(column);
                fileFolder0.setSort(sort);
                //打开权限文件夹
                fileFolders = fileMapper.getAuthorityFileFolder(fileFolder0);
                List<FileFolder> fileFolders2 = new ArrayList<>();
                for(FileFolder fileFolder: fileFolders){
                    if(fileFolder.getAuthorityLevel() == null) fileFolder.setAuthorityLevel("4");
                    else if(account.equals(fileFolder.getOwnerAccount())) fileFolder.setAuthorityLevel("4");
                    if(visibility != null && visibility.equals("true")){
                        fileFolders2.add(fileFolder);
                    }
                    else{
                        FileFolder fileFolderSearch = new FileFolder();
                        fileFolderSearch.setParentId(fileFolder.getEntityId());
                        fileFolderSearch.setOwnerAccount(account);
                        fileFolderSearch.setEntityRoom(depId);
                        if(!fileMapper.getAuthorityFileFolder(fileFolderSearch).isEmpty() || fileFolder.getTag() == null) {
                            fileFolders2.add(fileFolder);
                        }
                    }
                }
                fileFavorites = fileService.OpenPersonalFavorites(entityId, account);
                folderFavorites = OpenPersonalFavorites(entityId, account);
                for (FileFolder fileFolder : fileFolders2) {
                    //是否收藏
                    if (folderFavorites.contains(fileFolder.getEntityId())) fileFolder.setIsFavorite("true");
                    else if (fileFavorites.contains(fileFolder.getEntityId())) fileFolder.setIsFavorite("true");
                    else fileFolder.setIsFavorite("false");
                    //权限
                    fileFolder.setAuthorityLevel(authorityService.checkAuthority(account, depId, fileFolder.getEntityId()));
                }
                fileFolders = fileFolders2;
                break;
            default:
                return null;
        }
        return fileFolders;
    }

    @Override
    public List<String> OpenPersonalFavorites(String entityId, String account) {
        Folder folder = new Folder();
        folder.setParentId(entityId);
        return favoritesMapper.getFolderFavorites(folder, account);
    }

    @Override
    public List<Folder> getFolder(Folder folder) {
        return folderMapper.getFolder(folder);
    }

    @Override
    public String deleteFolderById(String entityId) {
        boolean result = folderMapper.deleteFolderById(entityId);
        if(result) return "删除成功!";
        else return "删除失败!";
    }

    @Override
    public String updateFolderById(Folder folder) {
        folder.setUpdateTime(Timestamp.valueOf(LocalDateTime.now()));
        boolean result = folderMapper.updateFolderById(folder);
        if(result) return "更新成功!";
        else return "更新失败!";
    }

    @Override
    @Transactional
    public String insertPersonalFolder(String account, String userName, String entityName, String parentId) {
        Folder folder = new Folder();
        folder.setEntityName(entityName);
        folder.setParentId(parentId);
        List<Folder> folders = folderMapper.getFolder(folder);
        if(!folders.isEmpty()) return "存在重名文件夹!";
        String roomId = roomService.getPersonalRoom(account);
        if(entityName == null || account == null) return "参数不全!";
        folder = new Folder();
        Timestamp time = (Timestamp.valueOf(LocalDateTime.now()));
        folder.setCreateTime(time);
        folder.setEntityName(entityName);
        folder.setEntityRoom(roomId);
        folder.setParentId(parentId);
        folder.setType("folder");
        folder.setOwnerAccount(account);
        folder.setOwnerName(userName);
        folder.setEntityId(generateEntityId());
        boolean result = folderMapper.insertFolder(folder);
        if(!result){
            log.error("insertPersonalFolder: 文件夹新增失败!");
            throw new BusinessException("文件夹新增失败!");
        }
        if(!updateParentTime(folder.getEntityId()).equals("修改时间修改成功!")){
            log.error("insertPersonalFolder: 修改时间修改失败!");
            throw new BusinessException("修改时间修改失败!");
        }
        return "新增成功!";
    }

    @Override
    @Transactional
    public String insertFolder(String account, String userName, String deptId, String roomId, String entityName, String parentId, String type) {
        String entityId = generateEntityId();
        Timestamp time = (Timestamp.valueOf(LocalDateTime.now()));
        if(type != null && (type.equals("dept") || type.equals("company"))){
            int level = Integer.parseInt(authorityService.checkAuthority(account, deptId, parentId));
            if(level < 3) throw new BusinessException("您没有编辑权限!");
            //自己的管理权限
            if(!authorityService.initAuthority(account, userName, entityId, "4").equals("新增权限成功!")){
                log.error("新增权限失败!");
                throw new BusinessException("新增权限失败!");
            }
        }

        Folder folder = new Folder();
        folder.setEntityName(entityName);
        folder.setParentId(parentId);
        List<Folder> folders = folderMapper.getFolder(folder);
        if(!folders.isEmpty()) throw new BusinessException("存在重名文件夹!");
        if(entityName == null || account == null){
            log.warn("参数不全!");
            throw new BusinessException("参数不全!");
        }
        //标签
        Folder parentFolder = new Folder();
        parentFolder.setEntityId(parentId);
        parentFolder = folderService.getFolder(parentFolder).get(0);
        folder = new Folder();
        folder.setCreateTime(time);
        folder.setEntityName(entityName);
        folder.setEntityRoom(roomId);
        folder.setParentId(parentId);
        folder.setType("folder");
        folder.setTag(parentFolder.getTag());
        folder.setIsOuter(parentFolder.getIsOuter());
        folder.setOwnerAccount(account);
        folder.setOwnerName(userName);
        folder.setEntityId(entityId);

        log.info("insertFolder: {}", folder);
        boolean result = folderMapper.insertFolder(folder);
        if(!result){
            log.error("insertFolder: 文件夹新增失败!");
            throw new BusinessException("文件夹新增失败!");
        }
        if(!updateParentTime(folder.getEntityId()).equals("修改时间修改成功!")){
            log.error("insertFolder: 修改时间修改失败!");
            throw new BusinessException("修改时间修改失败!");
        }
        if(type != null && (type.equals("dept") || type.equals("company"))){
            //继承父类权限
            List<Authority> authorities = authorityService.getAuthority(account, parentId);
            for(Authority authority: authorities){
                authority.setId(authorityService.generateId());
                authority.setEntityId(entityId);
                authority.setEntityName(entityName);
                authority.setUpdateTime(time);
                authority.setCreateTime(time);
                if(authority.getAuthorityLevel().equals("0.5")) continue;
                authorityService.insertAuthority(authority);
            }
        }
        return "新增成功!";
    }

    @Transactional
    @Override
    public String createFolder(String account, String userName, String roomId, String entityName, String parentId) {
        String entityId = generateEntityId();
        Timestamp time = (Timestamp.valueOf(LocalDateTime.now()));
        Folder folder = new Folder();
        folder.setEntityName(entityName);
        folder.setParentId(parentId);
        List<Folder> folders = folderMapper.getFolder(folder);
        if(!folders.isEmpty()) throw new BusinessException("存在重名文件夹!");
        //标签
        Folder parentFolder = new Folder();
        parentFolder.setEntityId(parentId);
        parentFolder = folderService.getFolder(parentFolder).get(0);
        folder = new Folder();
        folder.setCreateTime(time);
        folder.setEntityName(entityName);
        folder.setEntityRoom(roomId);
        folder.setParentId(parentId);
        folder.setType("folder");
        folder.setTag(parentFolder.getTag());
        folder.setIsOuter(parentFolder.getIsOuter());
        folder.setOwnerAccount(account);
        folder.setOwnerName(userName);
        folder.setEntityId(entityId);
        log.info("createFolder: {}", folder);
        boolean result = folderMapper.insertFolder(folder);
        if(!result){
            log.error("createFolder: 文件夹新增失败!");
            throw new BusinessException("文件夹新增失败!");
        }
        if(!updateParentTime(folder.getEntityId()).equals("修改时间修改成功!")){
            log.error("createFolder: 修改时间修改失败!");
            throw new BusinessException("修改时间修改失败!");
        }
        //继承父类权限
        List<Authority> authorities = authorityService.getAuthority(null, parentId);
        for(Authority authority: authorities){
            authority.setId(authorityService.generateId());
            authority.setEntityId(entityId);
            authority.setEntityName(entityName);
            authority.setUpdateTime(time);
            authority.setCreateTime(time);
            if(authority.getAuthorityLevel().equals("0.5")) continue;
            authorityService.insertAuthority(authority);
        }
        return "新增成功!";
    }

    @Transactional
    public String updateParentTime(String entityId) {
        String parent = "";
        if(entityId.startsWith("folder")){
            Folder folder = new Folder();
            folder.setEntityId(entityId);
            List<Folder> folders = folderMapper.getFolder(folder);
            if(folders.isEmpty()){
                PersonalRecycleBin personalRecycleBin = new PersonalRecycleBin();
                personalRecycleBin.setEntityId(entityId);
                List<PersonalRecycleBin> personalRecycleBins = personalRecycleBinMapper.getPersonalRecycleBin(personalRecycleBin);
                if(personalRecycleBins.isEmpty()) {
                    log.error("不存在该entityId!(1)");
                    throw new BusinessException("不存在该entityId!");
                }
                else parent = personalRecycleBins.get(0).getParentId();
            }
            else parent = folders.get(0).getParentId();
        }
        else if(entityId.startsWith("file")){
            File file = new File();
            file.setEntityId(entityId);
            List<File> files = fileMapper.getFile(file);
            if(files.isEmpty()) {
                PersonalRecycleBin personalRecycleBin = new PersonalRecycleBin();
                personalRecycleBin.setEntityId(entityId);
                List<PersonalRecycleBin> personalRecycleBins = personalRecycleBinMapper.getPersonalRecycleBin(personalRecycleBin);
                if(personalRecycleBins.isEmpty()) {
                    log.error("不存在该entityId!(2)");
                    throw new BusinessException("不存在该entityId!");
                }
                else parent = personalRecycleBins.get(0).getParentId();
            }
            else parent = files.get(0).getParentId();
        }
        Timestamp time = (Timestamp.valueOf(LocalDateTime.now()));
        while (!parent.equals("root")){
            Folder folder = new Folder();
            folder.setEntityId(parent);
            List<Folder> folders = folderMapper.getFolder(folder);
            log.info("updateParentTime: {}", folder);
            if(folders.isEmpty()){
                log.error("不存在该entityId!");
                throw new BusinessException("不存在该entityId!");
            }
            folder = folders.get(0);
            folder.setUpdateTime(time);
            folderMapper.updateFolderById(folder);
            parent = folder.getParentId();
            //修改收藏和分享
            Favorites favorites = new Favorites();
            favorites.setEntityId(parent);
            List<Favorites> favoritesList = favoritesMapper.getFavorites(favorites);
            if(!favoritesList.isEmpty()){
                favorites = favoritesList.get(0);
                favorites.setUpdateTime(time);
                if(!favoritesMapper.updateFavoritesName(favorites)){
                    log.error("收藏修改失败!(1)");
                    throw new BusinessException("收藏修改失败!");
                }
            }
            Shared shared = new Shared();
            shared.setEntityId(parent);
            List<Shared> shareds = sharedMapper.getShared(shared);
            if(!shareds.isEmpty()) {
                shared = shareds.get(0);
                shared.setUpdateTime(time);
                if (!sharedMapper.updateSharedName(shared)){
                    log.error("收藏修改失败!(2)");
                    throw new BusinessException("收藏修改失败!");
                }
            }
        }
        return "修改时间修改成功!";
    }


    @Override
    public String generateEntityId() {
        String uuid = UUID.randomUUID().toString();
        return "folder_" + uuid;
    }
}
